<?php 
/**create by fu */
namespace app\api\service;

use app\api\service\Order as OrderService;
use app\api\service\Token as TokenService;

use app\api\model\Order as OrderModel;
use app\lib\exception\OrderException;
use app\lib\exception\TokenException;
use app\lib\enum\OrderStatusEnum;
use think\Log;
use think\Loader;
// 加载 微信第三方非 命名空间的SDK
Loader::import('WxPay.WxPay',EXTEND_PATH,'.Api.php');
/**
 *   支付方法
 */
class Pay
{
	private $orderID;
	private $orderNo;
	function __construct($orderID)
	{
		if(!$orderID)throw new Exception("订单号不允许为空");

		$this->orderID = $orderID;
		
	}

	// 支付主方法
	public function pay()
	{
        // 检测订单号 是否存在
        // 查 订单号和当前用户是不是匹配
        // 是否已支付
		// 给订单号（公共属性）赋值
        // 库存检测
        $this->checkOrderValid();

		//支付前检查库存
		$orderService = new OrderService();
		$status = $orderService->checkOrderStock($this->orderID);
        
        if(!$status['pass']) return $status;

        return $this->makeWxpreOrder($status['orderPrice']);

	}

	// 微信预订单
	private function makeWxpreOrder($totalPrice)
	{
		//获取openid
		$openid = TokenService::getCurrentTokenVar('openid');
		if(!$openid)throw new TokenException();
		// 1 设置统一下单的所需参数
		$wxOrderData = new \WxPayUnifiedOrder();
		$wxOrderData->SetOut_trade_no($this->orderNo);             //传入订单号
		$wxOrderData->SetTrade_type('JSAPI');                      //传入交易类型
		$wxOrderData->SetTotal_fee($totalPrice*100);               //设置总金额 (单位：分)
		$wxOrderData->SetBody('零食商贩');                          //设置商品描述
		$wxOrderData->SetOpenid($openid);                          //设置用户标识
		$wxOrderData->SetNotify_url(config('secure.pay_back_url'));//回调url
		/**2 进行统一下单 
		 *    -> 获取预付单信息
		 *    -> prepay_id 存入数据表 
		 *    -> 并构建支付所需的签名
		 */ 
		return $this->getPaySignature($wxOrderData);
		

	}


	private function getPaySignature($wxOrderData)
	{   

		$wxOrder = \WxPayApi::unifiedOrder($wxOrderData);

		// 如果统一下单失败
		if($wxOrder['return_code'] != 'SUCCESS' || $wxOrder['result_code'] != 'SUCCESS')
		{
			Log::record($wxOrder,'error');
			Log::record('获取预支付订单失败','error');
			throw new \Exception("统一已下单失败;code=".$wxOrder['return_code'].';msg='.$wxOrder['return_msg'], 1);
			
		}
// $wxOrder['prepay_id'] = 99999;
		// 保存prepay_id 到数据表
		$this->recordPreOrder($wxOrder);
		// 构建签名 给客户端 调出支付页面
		$signature = $this->sign($wxOrder);

		return  $signature;

	}
	
	// 签名
	private function sign($wxOrder)
	{
		$rand = md5(time().mt_rand(0,1000));
		$jsApiPayData = new \WxPayJsApiPay();
		$jsApiPayData->SetAppid(config('wx.app_id'));  //设置appid
		$jsApiPayData->SetTimeStamp((string)time());   //千万注意string类型
		$jsApiPayData->SetNonceStr($rand);             //设置随机字符串
		$jsApiPayData->SetPackage('prepay_id='.$wxOrder['prepay_id']);//千万注意拼接'prepay_id='
		$jsApiPayData->SetSignType('md5');
		// 获得签名
		$sign = $jsApiPayData->MakeSign();

		// 最后获得包含签名和所输入的参数形成的数组
		$rawValues = $jsApiPayData->GetValues();
		$rawValues['paySign'] = $sign;
		unset($rawValues['appId']);

		return $rawValues;

	}
	// 保存prepay_id 到数据表里
	private function recordPreOrder($wxOrder)
	{
		OrderModel::where('id','=',$this->orderID)
		          ->update(['prepay_id'=>$wxOrder['prepay_id']]);
	}

	/** 检查订单ID的有效性
	 *  1 根据订单ID 查订单信息
	 *  2 提出用户ID 校验  
	 *  3 提出订单状态校验
	 */
	private function checkOrderValid()
	{
		$order = OrderModel::where('id','=',$this->orderID)->find();
		if(!$order)throw new OrderException();
        
        //提出用户ID 校验 
		if(!TokenService::isValidOperate($order->user_id)){
			throw new TokenException([
				'msg' => '订单与用户不匹配',
				'errorCode' => 10003,
			]);
		}

		//提出订单状态校验
		if($order->status != OrderStatusEnum::UNPAID)
		{
			throw new OrderException([
				'msg'       => '订单已经支付了',
				'errorCode' => 80003,
				'code'      => 400
			]);
			
		}

		$this->orderNo = $order->order_no;
		return true;

	}
}









 ?>